home *** CD-ROM | disk | FTP | other *** search
- Path: mirror!adelie!necntc!husc6!seismo!munnari!sources-request
- From: sources-request@munnari.oz
- Newsgroups: mod.sources
- Subject: v08i081: Graph+, A Graph Plotting Program, Part01/03
- Message-ID: <1431@munnari.oz>
- Date: 28 Feb 87 07:35:08 GMT
- Sender: kre@munnari.oz
- Lines: 2167
- Approved: kre@munnari.oz.au
-
- Submitted by: Alan Kent <ajk@goanna.oz.au>
- Mod.sources: Volume 8, Issue 81
- Archive-name: graph+/Part01
-
- #! /bin/sh
- # This is a shell archive, meaning:
- # 1. Remove everything above the #! /bin/sh line.
- # 2. Save the resulting test in a file
- # 3. Execute the file with /bin/sh (not csh) to create the files:
- #
- # README
- # graph+.1
- # Makefile
- # bar_graph
- # best_fit
- # graph.h
- # yacc.y
- #
- # Created by ajk on Wed Feb 25 09:23:09 EST 1987
- #
- if test -f 'README'
- then
- echo shar: will not over-write existing file "'README'"
- else
- echo extracting "'README'"
- sed 's/^X//' >README <<'SHAR_EOF'
- XA Graph Plot Program:
- X
- XI have found this program extremely useful for generating line plots from
- Xtables of data. It provides quite powerful operators to maniuplate and
- Xjoin different tables of numeric data. It does not do bar graphs, pie charts
- Xetc., although it could be modified to do so (and no, I am not volunteering!)
- X
- XIt can also be used as a desk calculator or to print tables of results
- Xon the screen rather than as a graph. I personally prefer it to using
- Xdc and bc quite often (but then I am probably biased). Just type graph+
- Xthen 'print 1/log(3);' etc. I also use it interactively to check data
- Xfiles, find how many entries have a column with values in a certain range
- Xand so on. For example
- X data = read "datafile"
- X print count ( data where $1 > 0 && $1 < 10)
- X
- XThe program here is not interactive like GNUPLOT but an alternative which
- Xprovides greater flexability in the preparation of data before it is plot
- X(I think). Since it can be used in a non-interactive fashion, it can
- Xbe used in makefiles (I use Makefiles to keep documents which include
- Xgraphs up to date).
- X
- XThis program requires lex and yacc, and at present has calls to ctime()
- Xand getenv() (although these last two calls are not critical). It also
- Xrequires the standard unix plot(3X) library. Output is in plot(5) format
- Xwhich must be fed through a filter program before it can be displayed.
- XThe maths library is used extensively to provide the same functions in
- Xgraph+, but the actual code only really needs log() and pow().
- X
- XI hope it is of some use to someone.
- X
- XAt the end of this file are instructions for patching this program
- Xfor your system.
- X
- XBrief History
- X=============
- X
- XAfter needing some graphs plotted and finding that the only really available
- Xcommand I could find was graph(1), I decided to write my own. I also found
- Xthat awk was too slow for my liking when trying to extract data from lots
- Xof files to be reformatted in some way. Thus graph+ was born. Graph+ requires
- Xa program (much like a shell script) to drive it. It allows files of data
- Xto be loaded as two dimensional arrays and then allows many commands to
- Xmanipulate the data. For example
- X
- X data = read "data.file"
- X graph data where $1 > 0 [ $2 , $3 + $4 ] dotted line label "data"
- X
- Xwill plot a graph of the data in the file data.file but will only plot
- Xpoints where the first column in the file has values greater than zero,
- Xand the data to plot will be column 2 (x) vs the sum of the values in
- Xcolumn 3 and 4 (y).
- X
- XWhen plotting the graph, different types of lines can be used (solid,
- Xdotted, dot dashed, short dashed, long dashed) or each point can be
- Xseparately marked (with triangles, squares, circles, crosses).
- XAll the scaling and numbering of the axis is done automatically
- Xalthough most values can be over-ridden.
- X
- XThe program also allows functions to be defined with sufficent power
- Xto do a least-squares best fit algorithm.
- X
- XThe software was not written for efficency (it can be memory hungry
- Xas all the table operations tend to make copies when performing the
- Xoperations) but I have not found memory to be a problem yet (well,
- Xnot on our vax anyway!)
- X
- XAll output is in standard plot(1) format as it uses the -lplot libraries.
- X
- XThis software should be fairly portable across UNIX systems although
- Xa little work may be required for other systems (like IBM PCs).
- X
- XCOMMON PROBLEMS
- X===============
- X
- XThe automatic scaling mechanism still does not always work correctly.
- XIt is actually very difficult to do properly. If strange things appear
- Xto be happening, try specifiying from and to on the xaxis and yaxis
- Xstatements (xaxis from 0 to 1000). Also, there can only be one xaxis
- Xand yaxis command per plot - multiple commands will ignore preceeding
- Xcommands.
- X
- XMost of the automatic features can be overriden manually.
- X
- X
- XPossible Patching Problems:
- X
- Xo The file main.c contains a path name that needs to be patched.
- X This is because the program looks in some special directories for
- X predefined funtions (if you wish to install any). (See GLOB_LIB)
- X The path can be defined in the Makefile instead.
- X
- Xo The last function in main.c may also need to be re-written for your machine
- X as it tries to determine what caused a floating exception. It will
- X probably work without any alterations. It is patched for our VAX 11/750
- X running BSD 4.2 at the moment.
- X
- Xo The file main.c uses getenv() and the file yacc.y uses time(),
- X ctime() and system() (for the shell statement).
- X
- Xo The include statement may not work as it involves fiddling with yacc.
- X At present it chews one token more than I really want it to.
- X
- Xo If your library does not contain relevant maths functions, either
- X just delete the code, insert a dummy function, or whatever. Note
- X that the code assumes all math functions have extern double func();
- X in <math.h> so if the function is not in the library, you will
- X probably have to add your own extern's where necessary.
- X
- Xo dumpgrph.c needs to know the width of a character!! This of course
- X changes per output device. If the macro LASER is defined, it seems
- X to work ok with our apple laser printer (helvetica), otherwise
- X it works for a tektronics emulator on a Sun we have here. The size
- X of a character must be known so that centering and right justification
- X can be done (for titles, numbers along axis etc).
- X
- Xo -lplot should be used in the Makefile for the most general form
- X of the program. Output can then be fed into plot(1) which re-maps
- X it for differnt terminal types. If however there is only one terminal
- X you are ever going to use it on (eg: a Tektronics 4014) then there
- X may be a plot library available on your machine so you can use
- X -l4014 and not have to type graph+ ... | plot ... all the time.
- X On the Sun for example there is a tektronics emulator which I use
- X for previewing graphs (they NEVER come out quite right the first time).
- X
- XAlan Kent,
- XDept Computer Science,
- XRoyal Melbourne Institute of Technology,
- XMelbourne, Australia.
- X
- XACSNet: ajk@goanna.oz
- XUUCP: {seismo,hplabs,mcvax,ukc,nttlab}!munnari!goanna.oz!ajk
- XARPA: munnari!goanna.oz!ajk@SEISMO.ARPA
- SHAR_EOF
- if test 6129 -ne "`wc -c < 'README'`"
- then
- echo shar: error transmitting "'README'" '(should have been 6129 characters)'
- fi
- fi
- if test -f 'graph+.1'
- then
- echo shar: will not over-write existing file "'graph+.1'"
- else
- echo extracting "'graph+.1'"
- sed 's/^X//' >graph+.1 <<'SHAR_EOF'
- X.\" Nroff -man
- X.de SY
- X.sp
- X.SH SYNTAX
- X.PP
- X.nf
- X..
- X.de ES
- X.SH EXAMPLES
- X.PP
- X.nf
- X..
- X.de EE
- X.fi
- X.SH DESCRIPTION
- X..
- X.TH graph+ ajk "31 January 1984"
- X.SH NAME
- Xgraph+ \- powerful graph generator program
- X.SH SYNOPSIS
- X.B graph+
- X[ commandfile | \- ]
- X[ parameter ... ]
- X.SH DESCRIPTION
- X.PP
- X.I Graph+
- Xis a utility program for producing graphs.
- XIts main advantage is that
- Xit allows easy manipulation of data using dynamic tables
- Xin memory using a relational style language (project etc.)
- Xrather than requiring a number of separate programs piped together.
- X.I Graph+
- Xalso allows functions to be defined returning values or tables.
- X.PP
- XBy placing the line
- X.PP
- X.in +4
- X #! /usr/rmit/graph+
- X.in -4
- X.PP
- Xat the beginning of a
- X.I graph+
- Xcommand file, the file can then be executed
- Xdirectly like a shell script, assuming that the binary file is in /usr/rmit.
- XOutput is in the format for input to the
- X.IR plot (1)
- Xfilters.
- X.PP
- XThe parameters can be referenced inside a plot program. The first parameter
- Xis given the number 1. This allows file names and graph titles to be
- Xpassed to a graph+ program. (See strings). If parameters are to be
- Xsuppied, but the actual program is on standard input, then \- must
- Xbe specified for the program file name. 'parms' is set to the number
- Xof parameters. Note that numeric parameters can be handled by using
- Xthe val() function.
- X.PP
- XIn
- X.IR graph+ ,
- Xa
- X.I table
- Xis a simple two dimensional array of floating point numbers.
- XTables can have any number of rows and columns.
- XData to be plotted is usually kept in files in a multicolumn format
- Xwith each line representing one piece of related data (say results
- Xfrom one experiment). An
- X.I awk
- Xprogram can be used to extract data from a complexly structured data
- Xfile or from files containing text and reformat into columns of data
- Xif necessary.
- X.I Graph+
- Xdoes not allow text to
- Xbe read \- only floating point data.
- X.PP
- XAnywhere a
- X.I string
- Xcan appear, a string expression is allowed.
- XA string expression can consist of a list of concatenated strings
- Xsepearated by + symbols.
- XLiteral strings
- Xare enclosed in double quotes (").
- XTo embed a double quote in the string, place two double quotes
- Ximmediately adjacent to each other.
- XAlternatives for literal strings include the word
- X.I parameter
- Xfollowed by the parameter number (the first parameter is number 1).
- XThe reserved word
- X.I date
- Xreturns a string which consists of the
- Xcurrent time and date (UNIX format).
- XThe function
- X.I val(string)
- Xreturns the numeric value of a string.
- XThe function
- X.I str(expr)
- Xreturns a string containing the result of printf("%g",expr).
- XThe function
- X.I str(format,expr)
- Xallows your own printf format to be used.
- X.PP
- XA
- X.I graph+
- Xprogram consists of a number of statements.
- X.SH STATEMENTS
- X.PP
- XThe ';' is treated as a null statement. It can be used at between other
- Xstatements if desired. When graph+ is used interactively (ie. type
- Xgraph+ with no parameters) commands can be entered but due to the
- Xlook-ahead parser, the next statement must be entered before the
- Xexisting one is processed. Adding a ; to the end of the command
- Xthen causes the parser to realise that the end of a statement has
- Xbeen reached. Note also that due to problems with yacc(1), the
- Xinclude statement requires a ; after it (see below).
- X.SY
- Xassume <expr> <string>
- X.ES
- Xassume parms=3 "3 parameters expected: "+str(parms)+" parameters given"
- Xassume count(data) > 0 "data table empty"
- X.EE
- X.PP
- X.I Assume
- Xaborts a graph+ program if the expression evaluates to false.
- XThis allows simple checks for table sizes, numbers of parameters
- Xetc. to be inserted in a program and an error message to be
- Xprinted.
- X.SY
- X<tab_ident> = <table>
- X.ES
- Xdata = read "data.file"
- X.EE
- X.PP
- XDefines the identifier
- X.I tab_ident
- Xto have the specified table of values.
- XTable identifiers may be referred to in
- X.I table
- Xexpressions. In the declaration,
- X.I tab_ident
- Xmust not have been already
- Xdefined unless it has already been defined as a table.
- X.SY
- X<var_ident> = <expr>
- X.ES
- Xpi = 3.1415
- X.EE
- X.PP
- XSimilar to a table declaration, except that the identifier has a single
- Xnumeric value assigned to it instead of a complete table.
- X.SY
- X<ident> ( <dec_parm_list> ) = <expr>
- X<ident> ( <dec_parm_list> ) = <table>
- X.ES
- X# this function returns the ratio of two numbers
- X
- Xa = 0
- Xb = 0
- Xratio(a,b) = a/b
- X
- X# this function limit returns a table of values where column
- X# 1 is less than the specified limit
- X
- Xlimit_val = 0 # declare parameters
- Xlimit_tab = {{0}} # declares a table
- Xlimit ( limit_tab , limit_val ) = limit_tab where $1 < limit_val
- X.EE
- X.PP
- XDeclares a function which returns
- Xa simple value or a table of values.
- XFunction identifiers can never be redefined.
- XThe parameter lists consist of a comma separated list of
- X.I tab_ident
- Xor
- X.I var_ident
- Xidentifers
- X.B "which must have been previously defined"
- X(see above example).
- XThese identifiers will act as parameters to the functions in the following
- Xway. When the function is called, the identifiers are redeclared with
- Xthe parameter values. Care must be taken for nested function calls as if they
- Xuse the same identifier names for parameters, the parameters to function
- XA might be changed after returning from a call to function B.
- XIt is common to declare special variables for parameters to functions
- Ximmediately before the actual function to be certain of the parameter type.
- X.SY
- Xinclude <string> ;
- X.ES
- Xinclude "bar_chart.g" ;
- X.EE
- X.PP
- XThe
- X.I include
- Xstatement allows another file of
- X.I graph+
- Xcommands to be included. This is useful for including function declarations.
- XThe ; is needed only because of the current implementation of the parser.
- XWhen an include is done, one token after the string is accidently lost.
- XThis may not be consistant across implementations of yacc and lex.
- X.SY
- Xshell <string>
- X.ES
- Xshell "awk -f complex.awk prelimfile > finalfile"
- Xdata = read "finalfile"
- X.EE
- X.PP
- XThe
- X.I shell
- Xcommand allows a command to be passed to the shell 'sh'.
- XThis can be used
- Xto generate a file to be read by including an output redirection.
- X.SY
- Xprint <table>|<expr>|<string>
- Xprint > <string> <table>|<expr>|<string>
- Xprint >> <string> <table>|<expr>|<string>
- X.ES
- Xprint "saving data to file copy.of.data" # print message on screen
- Xprint > "copy.of.data" data # save data on a file
- Xprint >> "copy.of.data" more_data # append some more data
- X.EE
- X.PP
- XThe
- X.I print
- Xcommand can have its output redirected (overwrite or append) to a
- Xfile called
- X.I <string>
- Xand print out a table, the result of an expression or a simple string.
- XIf two prints to the same file are used, make sure the second is and
- Xappend redirect (>>).
- X.SY
- Xsave <table> as <string>
- X.ES
- Xdata = read "text.data"
- Xsave data as "data.binary"
- Xprint > "text.data" load "data.binary" # converts a binary file back to text
- X.EE
- X.PP
- XThe
- X.I save
- Xcommand saves the table of data in binary format for faster loading
- Xwith the
- X.I load
- Xcommand. This is useful when a large datafile is to be read a number
- Xof times by different plot programs as the binary file can be loaded
- Xmuch more quickly than textual versions. It is also possible that
- Xthe binary file will require less disk space. The format of the
- Xbinary file is simply two integers (number of columns and number
- Xof rows) followed by all the data (doubles).
- XThe data is written out column by column so the first double is
- Xthe first value in the first column, the second value is the
- Xsecond value in the first column and so on.
- XBinary files may not be transportable across machines.
- X.SY
- Xgraph <table> [ <option> ... ]
- X<option> = no|solid|dotted|shortdashed|longdashed|dotdashed line
- X<option> = no|triangle|circle|square|cross|plus points
- X<option> = label <string>
- X<option> = legend <string>
- X.ES
- Xgraph data
- Xgraph data2 dotted line
- Xgraph data3 dotdashed line label "data3"
- Xgraph data no line cross points circle points # put a circle and cross
- Xgraph {{10,20}} label "text at 10,20"
- X.EE
- X.PP
- XThe
- X.I graph table
- Xcommand specifies details of an actual graph to plot. The table specified
- Xmust have exactly two columns, the first column being for x coordinatates and
- Xthe second for y coordinates. Multiple
- X.I graph
- Xcommands will cause multiple graphs to be drawn on the same axis.
- X.PP
- XThe graph options allow the type of line to draw the graph to
- Xbe specified (default is solid) and for a label to be printed on the
- Xfinal graph after the last point of the data. Note that text can be
- Xpositioned anywhere on a graph by using a constant table and a label
- X(as in the example above).
- X.PP
- XThe
- X.I legend
- Xoption can be used instead of the label option if a separate legend
- Xis wanted. The label option often fails when more than one graph end
- Xat the same point causing the labels to be overwritten making them
- Xunreadable. The
- X.I put
- X.I legend
- X.I at
- Xstatement can be used to position the legend on the graph (the legend
- Xcannot be put below the graph).
- X.PP
- XThe point information (circle, triangle etc) is drawn per point in the
- Xgraph. The
- X.I "no line"
- Xoption must be used if only the points are to be
- Xmarked. The default points value is
- X.I "no points."
- XNote that multiple
- Xpoints options on the same graph statement will cause the different
- Xtypes of points to be superimposed. This means a crossed circle can
- Xbe done using
- X.I "crossed points circle points."
- XNote that only one line type can be specified however.
- X.SY
- Xgraph label <string>
- X.ES
- Xgraph label "Statistics for the year 1986 " + date
- X.EE
- X.PP
- XAllows a label to be placed at the top of the graph.
- XIf this command is not specified, no label
- Xis printed. Note that the string (as like all other strings)
- Xcan be a concatenation of literal strings and other
- Xbuilt in operators (like
- X.IR date ).
- X.SY
- Xxaxis [ <axis_option> ... ]
- Xyaxis [ <axis_option> ... ]
- X<axis_option> can be one of
- X label <string> (default none)
- X format <string> (default depends on range of data)
- X auto|no scale (default auto scale)
- X frame|grid|outline|no axis (default grid axis)
- X logarithmic|linear (default linear)
- X from <expr> to <expr>
- X tick size <expr> [ power <expr> ]
- X.ES
- X# xaxis will have all values marked and vertical lines drawn over the
- X# whole graph per tick value
- Xxaxis label "Year" format "%4f"
- X from 1980 to 1986 tick size 1
- X# yaxis will have only the tick values drawn (no horizontal lines)
- X# The data will be made logarthmic and the label will be spilt over
- X# two lines: "Population" and "per year"
- Xyaxis frame axis logarithmic label "Population per~year"
- X
- X# another example with ticks
- Xyaxis tick size 2 power 3 # ticks are really of size 2000 (2 x 10^3)
- X.EE
- X.PP
- XThe
- X.I xaxis
- Xand
- X.I yaxis
- Xstatements allow details to be specified on how the x and y axis lines
- Xfor the graph frame should be drawn.
- X.PP
- XThe
- X.I label
- Xoption is used to define what label to place on the axis.
- XOn the Y axis, the words (separated by blanks) are placed on separate lines
- Xone above the other. To place two words on the same line
- X(for example if there are two short words) use a '~' instead
- Xof a space. When the label is printed, the '~' will be changed
- Xinto a blank.
- XThe best way to write the label would be by rotating the text
- Xby 90 degrees, but the plot(1) format does not allow this.
- X.PP
- XThe
- X.I format
- Xoption allows a printf format string for a long floating point number
- X('double' in the 'C' programming language)
- Xfor printing the numbers on the ticks along the axis. No checking of
- Xthis format string is made. The default format is generally acceptable.
- X.PP
- XThe
- X.I scale
- Xoption allows the values along the axis to be automatically scaled by
- Xlabeling the axis as 'x 10^n' where n is the power. For example,
- Xfor values from 0 to 10000 may be shown on the ticks as from 0 to 10.0
- Xwith a factor of 10^3. The default is to
- X.I auto
- X.I scale
- Xbut the
- X.I no
- X.I scale
- Xoption can inhibit this.
- X.PP
- XThe
- X.I axis
- Xoption allows different forms of axis lines to be drawn.
- XNormally both axis will be given the same axis type, but this
- Xis not necessary.
- XThe
- X.I frame
- Xoption simply draws a single line along which ticks are place with
- Xnumeric values.
- XThe
- X.I grid
- Xoption draws a grid over the whole graph.
- XThe
- X.I outline
- Xoption is very similar to the
- X.I frame
- Xoption but a second line is drawn on the far side of the graph.
- XIf this option is used on both axis or with a grid on the other axis,
- Xthe graph will appear to be enclosed in a box.
- XIf no axis (and no numbering) is desired, use the
- X.I no
- Xoption.
- XThe best way to find out what these do exactly is to experiment.
- X.PP
- XThe
- X.I linear
- Xand
- X.I logarithmic
- Xoptions allow a simple linear (default) or logarithmic graph to be
- Xplotted.
- X.PP
- XThe
- X.I from
- Xclause allows the range of values for the axis to be specified.
- XBy default this is calculated from the graphs to be plotted by
- Xdetermining the minimum and maximum values.
- X.PP
- XThe
- X.I tick
- X.I size
- Xclause allows the tick sizes to be specified. Normally this option would
- Xnot be used as graph+ tries to automatically calculate a nice looking
- Xvalue for the tick size and power (based on how much will fit on the output).
- XFractions for tick sizes (eg 1.33333) do not work well and due to rounding
- Xproblems may cause tick marks to be skipped along the axis. Round numbers
- Xshould be safe.
- XIf
- X.I power
- Xis not specified, then it is defaulted to 0. If a value of say 3 is used,
- Xthen the tick values will really be the tick size specified by 10^3 and
- Xthe power will be printed below the axis label in the form 'x 10^3'.
- X.SY
- Xput legend at top|middle|bottom left|center|right
- X.ES
- Xgraph data1 dotted line legend "graph 1"
- Xgraph data2 solid line legend "graph 2"
- Xput legend at bottom left
- Xplot
- X.EE
- X.PP
- XThe
- X.I put
- X.I legend
- X.I at
- Xstatement is used to position the legend on the graph. The legend
- X(at present) is drawn on top of the actual graph (underneath may
- Xbe better, but is harder due to the way the plot(1) functions work).
- XThe top/middle/bottom option selects the verical positioning and
- Xthe left/center/right option selects the horizontal positioning.
- XThe default position is the top right corner of the graph.
- X.SY
- Xplot
- X.ES
- Xgraph data1 solid line
- Xgraph data2 dotted line
- Xplot
- Xgraph data3 dotted line
- X.EE
- X.PP
- XThe
- X.I plot
- Xcommand generates a plot of all the graph statements done so far.
- XAny following graph commands will appear on the next plot.
- XA plot command is automatically performed at the very end of
- Xa command file if any graph statements have been found.
- X.SH TABLES
- X.PP
- XA <table> can be an expression made up from any of the following
- Xsub-expressions. These usually appear directly in
- X.I graph
- Xstatements, or when assigned to a table variable.
- X.SY
- Xread <file_name_string>
- Xread <cols_expr> by <rows_expr> <file_name_string>
- X.ES
- Xdata = read "data.file"
- Xgraph read 2 by 200 "data.file" # I know the file is 2 colums by 200 lines
- Xdata = read parameter 2 + ".dat"
- X.EE
- X.PP
- XThe
- X.I read
- Xcommand reads a table from a file. Blank lines
- Xand all characters from # to the end of line are ignore (allowing
- Xcomments to be put in data files). The number
- Xof columns in the table is determined by reading the first non-blank
- Xline in the file. The number of rows is determined by counting
- Xthe number of non-blank lines in the file. To read a file, two passes
- Xare made \- the first to determine the table size so a table can be
- Xallocated enough memory, and a second to read the actual values.
- X.PP
- XThe second form of the
- X.I read
- Xcommand allows the dimensions of the table to be prespecified so that
- Xonly one pass of the file is needed. This makes the command slightly
- Xfaster but much less flexible to changes in the data file. The first
- X.I expr
- Xspecifies the number of columns (which must be correct)
- Xand the second specifies the number of rows (which can be too large \-
- Xthe table is simply truncated although enough memory is allocated for
- Xthe full table.
- X.PP
- XThe ability to create strings from concatenations of sub-strings
- Xis very useful when specifying a filename. In particular, the
- Xability to extract parameters to the command allows the same
- Xplot program to be used with several data files.
- X.SY
- Xload <string>
- X.ES
- Xdata = load "data.file"
- X.EE
- X.PP
- X.I load
- Xis very similar to
- X.I read
- Xexcept that it loads a binary file saved with the
- X.I save
- Xcommand. The binary file format is described under the
- X.I save
- Xcommand.
- X.SY
- X{ { <expr> , <expr> , ... } { <expr> , <expr> , ... } ... }
- X.ES
- Xconst_table = { {0,0} {1,2} {3,10} {4,20} } # 2 cols, 4 rows
- Xcalc_table = { {0,log(0)} {10,log(10)} {100,log(100)} }
- Xgraph {{10,20}} label "label at 10,20 on graph"
- X.EE
- X.PP
- XBraces allow a table of expressions to be specified.
- XOne set of braces surround
- Xthe whole table, each row in the table being specified by a comma
- Xseparated list of expressions surrounded in one set of braces per row.
- X.SY
- Xgenerate from <expr> to <expr> <interval>
- X<interval> = with <expr> intervals
- X<interval> = interval size <expr>
- X.ES
- Xtab_size = 10
- Xlog_table = generate from 1 to tab_size interval size 1 [ $1 , log($1) ]
- Xsingle_col_table = generate from 1 to 100 with 11 intervals
- X.EE
- X.PP
- XThe
- X.I generate
- Xcommand generates a single column table of values in the specified from\-to
- Xrange using the specified interval details.
- X.SY
- X<table> append <table>
- X.ES
- Xtotal_dat = dat1 append dat2
- X.EE
- X.PP
- XThe
- X.I append
- Xcommand appends the second
- X.I table
- Xto the end of the first
- X.I table.
- XBoth tables must have the same number of columns.
- X.SY
- X<table> adjacent <table>
- X.ES
- Xwide_tale = dat1 adjacent dat2
- X.EE
- X.PP
- XThe
- X.I adjacent
- Xcommand is similar to the
- X.I append
- Xcommand, but it joins tables horizontally instead of vertically.
- XBoth tables can have different numbers of columns, but must have the
- Xsame number of rows.
- X.SY
- X<table> [ <expr> , <expr> , ... ]
- X.ES
- Xgraph all_data [ $1 , $3 ] # plot columns 1 vs 3
- Xgraph all_data [ $0 , ($1+$3)/2 ] # plot the average of column 1 and 3
- X.EE
- X.PP
- XThe projection command (square brackets) allows data to be extracted
- Xfrom a table, or new columns of data to be formed from expressions based
- Xon existing columns of data. See the
- X.I expr
- Xfor exact details of how to extract columns of data from a table.
- XThe number of rows in the new table is the same as the number of
- Xrows in the old table, but the number of columns is dependent on the
- Xnumber of expressions in the comma separated list of expressions inside
- Xthe square brackets.
- X.SY
- X<table> where <expr>
- X.ES
- Xsome_data = data where $0 <= 100 # select first 100 entries in table
- Xsome_data = data where $1 >= $2/2 # select lines where first column is
- X # greather than or equal to half the second column
- X.EE
- X.PP
- XThe
- X.I where
- X(or selection) command forms a new table with the same number of columns
- Xas the old table, but only containing rows that satisfy the condition
- X.I expr.
- XThe expression normally uses relational operators such as <, >= etc.
- Xbut any expression can be used. A return value of 0.0 is considered as
- Xfalse, any other value being true (as in the 'C' programming language).
- X.SY
- Xsort <table> by <attr>
- X.ES
- Xdata = sort data by $2
- X
- X# sort table of two columns by the sum of the two columns
- Xsorted_data = sort ( data [ $1 , $2 , $1+$2 ] ) by $3 [ $1 , $2 ]
- X.EE
- X.PP
- XThe
- X.I sort
- Xcommand allows a table to be sorted by a column in the table specified by
- X.I attr.
- XThe column specified cannot be column zero (which has a special use).
- XAn
- X.I attr
- Xwas used to sort on instead of any expression for efficency reasons.
- XTo sort by an expression, simply project an extra column into the table
- Xbefore sorting, and remove it (with another project) later.
- XThe sort algorithm used is a version of quicksort.
- X.SY
- Xjoin <table1> , <table2> by <attr1> , <attr2>
- X.ES
- Xdata = join dat1 , dat2 by $1 , $1
- X.EE
- X.PP
- XThe
- X.I join
- Xcommand performs an equi-join on the two tables of data.
- X<attr1> and <attr2> specify the fields on which the join is
- Xto be performed. If the data in the two tables is not found
- Xto be sorted on the join fields, the tables are sorted automatically.
- XThe join then creates a new table which contains all the columns
- Xof <table1> followed by all the columns of <table2> (the join
- Xfield is NOT removed and so will appear in the resultant table twice).
- X.SY
- Xcumulate <table> by <attr>
- X.ES
- Xgraph cumulate cost_per_unit by $2
- X.EE
- X.PP
- XThe
- X.I cumulate
- Xcommand takes a column in a table specified by
- X.I attr
- Xand replaces each entry with the sum of the present value and all the
- Xprevious values. This is useful for plotting cumulative graphs.
- X.SY
- Xgroup <table> [ from <expr> to <expr> ] <interval> performing <function>
- X.ES
- Xgraph group sort data by $1 with 10 intervals performing max [ ($1+$2)/2 , $3 ]
- Xdata = group data from 10 to 20 with interval size 5 performing average
- X.EE
- X.PP
- XThe
- X.I group
- Xcommand is fairly complex but allows graphs to be split into a number
- Xof intervals with the specified function
- X.RI ( fvar_ident )
- Xbeing called for each interval.
- XThe function must return a simple value and have a single parameter of
- Xa table (such as the predefined
- X.IR sum ,
- X.IR min ,
- X.IR max ,
- X.I count
- Xand
- X.I average
- Xfunctions.
- X.PP
- XThe group table must have exactly two colums, the first column
- Xbeing used for grouping by and the second containing the values to pass
- Xto the function. The table must have already been sorted on the first column.
- XProjects are often made to tables to get them into the
- Xcorrect form for a grouping.
- XThe optional range specification (if no range is specified, the minimum and
- Xmaximum values are calculated from the table) defines the upper and lower
- Xbound of values to be considered in the group.
- XThe interval specification is used to determine the number of and size of
- Xthe group intervals. Beware of intervals have no values in them. These
- Xwill cause the function to be called with an empty table.
- X.PP
- XThe result of a group has extactly three columns. The first two columns
- Xcontain the lower and upper bound values of the interval and the third
- Xcolumn contains the result of the function when applied to all of the
- Xvalues within that interval. From this, it is fairly simple to produce
- Xdifferent forms of graphs (eg bar graphs, line graphs).
- X.SY
- X<function_ident> ( <expr> , <expr> , ... )
- X.ES
- Xprint min ( data_table )
- Xprint average ( data_table[$3] )
- X
- Xtab = {{0}}
- Xftab(tab) = count ( tab[$1] ) / average ( tab[$2] )
- Xprint ftab({{1,1}{4,4}})
- X.EE
- X.PP
- X.I <function_ident>
- Xis a table function name which is called with the specified parameter list.
- X.PP
- XTable identifiers return the value of the table as last declared
- Xwith "=" or when declared as a parameter.
- X.SY
- X( <table> )
- X.ES
- Xsort ( data[ $1 , $3 ] ) by $2
- X.EE
- X.PP
- XSimple parenthisis allow the priority of evaluation to be forced.
- XDefault priority of table operators listed from highest priority to lowest is
- Xselect and project, adjacent, append, sort, group and cumulate.
- X.SH EXPRESSIONS
- X.PP
- XIn the following, a true value is considered to be any non-zero value,
- Xand false is considered to be the value 0.
- XThe operators are listed here from lowest to highest priority.
- X.SY
- X<expr> "?" <expr> ":" <expr>
- X.ES
- Xdata = data [ $1 , $2<=0 ? 0 : log($2) ]
- X.EE
- X.PP
- XThe
- X.I '?'
- Xoperator returns the value of the second
- Xexpression if the first expression is true; otherwise the value of the third
- Xexpression is returned.
- X.SY
- X<expr> || <expr>
- X.ES
- Xdata = data where $1<10 || $1>20
- X.EE
- X.PP
- XThe logical OR operator ('||') returns true if either expression returns
- Xtrue, false otherwise.
- X.SY
- X<expr> && <expr>
- X.ES
- Xdata = dat where $1>10 && $2<20
- X.EE
- X.PP
- XThe logical AND operator ('&&') returns true if both expressions return true,
- Xfalse otherwise.
- X.SY
- X<expr> =|==|<>|!=|<=|<|>|>= <expr>
- X.ES
- Xdata = data where $1>10 | $2 = 0
- X.EE
- X.PP
- XThese relational operators return true or false based on the operator
- Xand the results of the two expressions. Note that equivalence can be
- Xspecified with either '=' or '==' and inequivalence can be specified
- Xwith either '<>' or '!='.
- X.SY
- X<expr> +|\- <expr>
- X.ES
- Xprint data[ $1+$2 , $1\-$2 ]
- X.EE
- X.PP
- XThese are the simple arithmetic addition and subtraction operators.
- X.SY
- X<expr> /|*|% <expr>
- X.ES
- Xpi = 3.1415
- Xprint pi / 3
- Xprint pi * 3
- Xprint 100 % 3
- X.EE
- X.PP
- XDivide, multiply and modulus operators.
- X.SY
- X<primary> =
- X \- <primary>
- X ! <primary>
- X ( <expr> )
- X <attr>
- X <number>
- X <func_var_ident> ( <expr>|<table> , <expr>|<table> , ... )
- X <var_ident>
- X parms
- X.ES
- Xprint -3
- Xprint !3
- Xprint data[ $2 ]
- Xpi = 3.1415
- Xprint pi
- Xtab={{0}}
- Xsizeof ( tab ) = count ( tab )
- Xprint "table size should be 2"
- Xprint sizeof ( {{1},{2}} )
- X.EE
- X.PP
- X.I Primary
- Xexpressions are separated in the syntax as an attribute specification
- X(see
- X.IR attr )
- Xcan only be a
- X.I primary
- Xexpression, typically a simple number.
- X.PP
- XThe minus unary operator is for negation.
- X.PP
- XThe NOT ("!") operator returns the oposite boolean value of the expression.
- X.PP
- XParenthises allow the default operator precidence to be overridden.
- X.PP
- X.I Numbers
- Xare any floating point number.
- X.PP
- X.IR <fvar_ident> s
- Xare variable function names, the parameters being listed inside
- Xthe parenthises.
- X.PP
- X.IR <var_ident> s
- Xare variables defined with the "=" operator or by parameter passing.
- X.PP
- X.I parms
- Xreturns the number of command line parameters given to the program.
- XThis is really only of any use in an
- X.I assume
- Xstatement (assume parms = 3 "3 parameters expected").
- X.SY
- X<attr> = $ <primary>
- X.ES
- Xgraph data[ $1 , $2 ]
- Xsumcol = 3
- Xgraph data[ $1 , $sumcol ]
- Xgraph data[ $1 , $($1<100 ? 2 : 3 ) ] # choose column based on $1
- Xprint > "savefile" data[ $0 , $1 , $2 ]
- X.EE
- X.PP
- X.IR <attr> 's
- Xspecify which column of a table to use.
- XColumn numbers start from 1 and count upwards.
- XIn an expression, the value
- Xof that column is returned if used in a project or select type command
- Xfor which the expression is re-evaluated for every row of a table.
- XIn expressions, column zero may be specified which returns the row number
- X(starting from 1)
- Xof the row instead of data from the table.
- X.SH "PREDEFINED FUNCTIONS"
- X.PP
- XThere are a number of predefined funtions, all of which at present return
- Xvalues.
- X.TP
- X.BI str (expr)
- X.TP
- X.BI str (format,expr)
- XReturn a string containing the value of the given expression.
- XIf no format is specified, "%g" is used. The format is passed straight
- Xto sprintf().
- X.TP
- X.BI min (table)
- XReturn the minimum value in the first column of
- X.IR table .
- XIf the table is empty, a warning is printed on stderr and a value of 0.0 is
- Xreturned.
- X.TP
- X.BI max (table)
- XReturn the maximum value in the first column of
- X.IR table .
- XIf the table is empty, a warning is printed on stderr and a value of 0.0 is
- Xreturned.
- X.TP
- X.BI sum (table)
- XReturn the total of all the values in the first column of
- X.IR table .
- XIf the table is empty, a warning is printed on stderr and a value of 0.0 is
- Xreturned.
- X.TP
- X.BI count (table)
- XReturn the number of rows in
- X.IR table .
- X.TP
- X.BI average (table)
- XReturn the average value in the first column of
- X.IR table .
- XIf the table is empty, a warning is printed on stderr and a value of 0.0 is
- Xreturned. This is like doing a
- X.I sum
- Xdivided by a
- X.I count.
- X.PP
- XThe following mathmatical functions are straight from the math library
- Xand suffer from all their constraints (no checking is done). See section
- X3(M) in the Unix Programmers Manual.
- X.TP
- X.BI sqrt (expr)
- XReturn the square root of the given expression.
- X.TP
- X.BI log (expr)
- XReturn log10 of the given expression.
- X.TP
- X.BI ln (expr)
- XReturn the natural log of the given expression.
- X.TP
- X.BI exp (expr)
- XReturn e to the power of expr.
- X.TP
- X.BI pow (expr1,expr2)
- XReturn
- X.I expr1
- Xto the power of
- X.I expr2.
- X.TP
- X.BI floor (expr)
- XReturn the largest integer not greater than
- X.I expr.
- X.TP
- X.BI ceil (expr)
- XReturn the smallest integer not less than
- X.I expr.
- X.TP
- X.BI abs (expr)
- XReturn the absolute value of
- X.I expr.
- X.TP
- X.BI sin (expr)
- XReturn sine of
- X.I expr.
- X.TP
- X.BI cos (expr)
- XReturn cosine of
- X.I expr.
- X.TP
- X.BI asin (expr)
- XReturn arc-sine of
- X.I expr
- Xin the range from -pi/2 to +pi/2.
- X.TP
- X.BI acos (expr)
- XReturn arc-cos of
- X.I expr
- Xin the range 0 to pi.
- X.TP
- X.BI atan (expr)
- XReturn arc-tangent of
- X.I expr
- Xin the range -pi/2 to +pi/2.
- X.TP
- X.BI atan2 (expr1,expr2)
- XReturn arc-tangent of
- X.I expr1/expr2
- Xin the range -pi to +pi.
- X.TP
- X.BI sinh (expr)
- XReturn hyperbolic sine of
- X.I expr.
- X.TP
- X.BI cosh (expr)
- XReturn hyperbolic cosine of
- X.I expr.
- X.TP
- X.BI tanh (expr)
- XReturn hyperbolic tangent of
- X.I expr.
- X.TP
- X.BI hypot (expr1,expr2)
- XReturns the square root of the sum of the squares of
- X.I expr1
- Xand
- X.I expr2.
- X.TP
- X.BI j0 (expr)
- X.TP
- X.BI j1 (expr)
- X.TP
- X.BI jn (expr1,expr2)
- X.TP
- X.BI y0 (expr)
- X.TP
- X.BI y1 (expr)
- X.TP
- X.BI yn (expr1,expr2)
- XBessel functions.
- X.TP
- X.BI val (string)
- XReturn the numeric value of the specified string.
- XThis is particularly useful for getting numeric parameters from the
- Xcommand line.
- X.SH EXAMPLE
- X.PP
- XThe following are some simple examples to try and help show how to actually
- Xuse all these commands.
- X.PP
- X #! /usr/rmit/graph+
- X
- X # some constant tables
- X
- X file1={ { 0, 1 } { 1, 20 } { 2, 30 } { 3, 16 } { 4, 19 } { 5, 29 } }
- X file2={ { 0, 3 } { 1, 15 } { 2, 34 } { 3, 12 } { 4, 12 } { 5, 24 } }
- X
- X num = 6
- X
- X final = sort (file1 append file2 ) by $1
- X
- X # the output of graph can not be directly printed.
- X # turn a graph table into a list of lines through
- X # the middle of each interval by forming a table
- X # with the first column being the middle of the group
- X # interval (the average of the first two columns) and
- X # the other column being the actual data
- X
- X lineg_tab={{0}} # dummy declaration for function parameter
- X lineg(lineg_tab) = lineg_tab[ ($1+$2)/2 , $3 ]
- X
- X graph lineg( group final with num intervals performing max )
- X graph lineg( group final with 10 intervals performing min )
- X graph file1 label "file"
- X graph cumulate(file1) label "cumulative"
- X
- X xaxis label "This is the x-axis"
- X yaxis label "This is~the y-axis"
- X # will appear
- X # This
- X # is the
- X # y-axis
- X.PP
- XA more typical example is
- X.PP
- X data1 = read "results.1"
- X data2 = read "results.2"
- X graph data1[ $1 , $2 ] dotted line label "first results"
- X graph data2[ $1 , $2 ] shortdashed line label "second results"
- X graph ( data1[$1,$2] adjacent data2[$2] ) [ $1 , ($2+$3)/2 ]
- X solid line label "average"
- X.SH DIAGNOSTICS
- X.PP
- XError recovery is poor. Syntax error can mean almost anything, the
- Xparse being a simple yacc program. Note that undefined identifiers
- X(due to typing errors) can also come up as syntax errors.
- X.SH BUGS
- X.PP
- XAlmost infinite. But the program in general does work. Its just that
- XI personally find the graphs are often not quite what I want.
- XIt is however MUCH better than the standard unix graph(1) command
- Xand allows good manipulation of data much faster than awk(1).
- X.PP
- XOne problem that can occur is running out of memory.
- XAll tables are held in memory - never on disk.
- XThe program works be continually building new tables from
- Xthe contents of old tables and then (if possible) freeing the
- Xold tables. Parameters after being called do not free the space
- Xconsumed by the parameter declaration, so large data files can
- Xcause a lot of memory to be held by the graph+ program.
- X.PP
- XThere would need to be several thousand more options to be able to
- Xprint all forms of graphs to keep everyone happy.
- X.PP
- XIf you have any problems, do not mail to ajk@goanna.oz ;-)
- X.SH AUTHOR
- XAlan Kent (ajk@goanna.oz)
- X.SH SEE ALSO
- Xleplot(ajk), awk(1), graph(1), plot(1), plot(3x).
- SHAR_EOF
- if test 30797 -ne "`wc -c < 'graph+.1'`"
- then
- echo shar: error transmitting "'graph+.1'" '(should have been 30797 characters)'
- fi
- fi
- if test -f 'Makefile'
- then
- echo shar: will not over-write existing file "'Makefile'"
- else
- echo extracting "'Makefile'"
- sed 's/^X//' >Makefile <<'SHAR_EOF'
- X
- XCFLAGS= -O -DGLOB_LIB=\"/r/pmr/ajk/lib/graph+rc\"
- X#CFLAGS= -O -DGLOB_LIB=\"/r/pmr/ajk/lib/graph+rc\" -DLASER
- X
- XLIBS= -lm -ll -lplot
- X#LIBS= -lm -ll -l4014
- X
- XYFLAGS= -d
- XPROG= graph+
- XOBJS= yacc.o lex.o \
- X abort.o adjacent.o appendtb.o attrnode.o average.o count.o \
- X cpyentry.o cpytable.o cumulate.o dumpgrph.o eval.o evaltab.o \
- X freetab.o fundeclr.o generate.o global.o group.o include.o \
- X join.o main.o max.o min.o new.o newtable.o numcols.o parmnode.o \
- X printtab.o project.o readtab.o reset.o saveload.o select.o sort.o \
- X sum.o tabdeclr.o tabnode.o vardeclr.o
- X
- XAll : $(PROG)
- X
- X$(PROG) : $(OBJS)
- X cc -o $(PROG) $(OBJS) $(LIBS)
- X
- Xshar :
- X shar README graph+.1 Makefile bar_graph best_fit graph.h yacc.y > g1.shar
- X shar [a-f]*.c > g2.shar
- X shar [g-z]*.c lex.l > g3.shar
- X
- Xclean :
- X /bin/rm $(OBJS)
- X
- Xlink :
- X cc -pg -o $(PROG) $(OBJS) $(LIBS)
- X
- X# following line needed if numbering of tokens change
- X# but otherwise just causes lots more compiles.
- X
- Xcumulate.o lex.o fundeclr.o dumpgrph.o eval.o evaltab.o \
- Xreset.o group.o main.o parmnode.o: y.tab.h
- X
- X$(OBJS): graph.h
- SHAR_EOF
- if test 1060 -ne "`wc -c < 'Makefile'`"
- then
- echo shar: error transmitting "'Makefile'" '(should have been 1060 characters)'
- fi
- fi
- if test -f 'bar_graph'
- then
- echo shar: will not over-write existing file "'bar_graph'"
- else
- echo extracting "'bar_graph'"
- sed 's/^X//' >bar_graph <<'SHAR_EOF'
- X
- XPARM = {{0}}
- X
- Xstep_graph ( PARM ) =
- X ( sort (PARM [ $0*2+1 , $1 , $3 ]
- X append
- X PARM [ $0*2+1 , $2 , $3 ] )
- X by $1 ) [ $2 , $3 ]
- X
- Xbar_graph ( PARM ) =
- X ( sort (PARM [ $0*4+1 , $1 , 0 ]
- X append
- X PARM [ $0*4+2 , $1 , $3 ]
- X append
- X PARM [ $0*4+3 , $2 , $3 ]
- X append
- X PARM [ $0*4+4 , $2 , 0 ] )
- X by $1 ) [ $2 , $3 ]
- X
- SHAR_EOF
- if test 338 -ne "`wc -c < 'bar_graph'`"
- then
- echo shar: error transmitting "'bar_graph'" '(should have been 338 characters)'
- fi
- fi
- if test -f 'best_fit'
- then
- echo shar: will not over-write existing file "'best_fit'"
- else
- echo extracting "'best_fit'"
- sed 's/^X//' >best_fit <<'SHAR_EOF'
- X
- XSxy_table = {{0}}
- XSxy( Sxy_table ) =
- X sum ( Sxy_table[ $1*$2 ] ) - ( 1 / count ( Sxy_table ) )
- X * sum ( Sxy_table[ $1 ] ) * sum ( Sxy_table [ $2 ] )
- X
- Xbeta_table = {{0}}
- Xbeta_func ( beta_table ) =
- X Sxy ( beta_table ) / Sxy ( beta_table[ $1 , $1 ] )
- X
- Xalpha_table = {{0}}
- Xalpha_func ( alpha_table ) =
- X average ( alpha_table[ $2 ] )
- X - beta_func ( alpha_table ) * average ( alpha_table[ $1 ] )
- X
- Xfit_Min = 0
- Xfit_Max = 0
- Xfit_Alpha = 0
- Xfit_Beta = 0
- Xline_fit2 ( fit_Min , fit_Max , fit_Alpha , fit_Beta ) =
- X {{ fit_Min , fit_Alpha + fit_Beta * fit_Min }
- X { fit_Max , fit_Alpha + fit_Beta * fit_Max }}
- X
- Xline_fit_table = {{0}}
- Xline_fit ( line_fit_table ) =
- X line_fit2 ( min ( line_fit_table[ $1 ] ) , max ( line_fit_table[ $1 ] ),
- X alpha_func ( line_fit_table ) , beta_func ( line_fit_table ) )
- X
- SHAR_EOF
- if test 789 -ne "`wc -c < 'best_fit'`"
- then
- echo shar: error transmitting "'best_fit'" '(should have been 789 characters)'
- fi
- fi
- if test -f 'graph.h'
- then
- echo shar: will not over-write existing file "'graph.h'"
- else
- echo extracting "'graph.h'"
- sed 's/^X//' >graph.h <<'SHAR_EOF'
- X/*
- X * Copyright (C) 1986 Alan Kent
- X *
- X * Permission is granted to freely distribute part or
- X * all of this code as long as it is not for profit
- X * and this message is retained in the code.
- X *
- X * No resposibility is taken for any damage or incorect
- X * results this program generates.
- X *
- X */
- X
- X
- X#define MAX_GRAPHS 30
- X
- Xtypedef struct table_st {
- X int size;
- X double *data;
- X struct table_st *next;
- X} table_st;
- X
- Xtypedef struct tnode_st {
- X int operator;
- X struct tnode_st *left , *right;
- X struct table_st *table;
- X struct expr_list_st *expr_list;
- X struct attr_st *expr;
- X char *ident;
- X double value;
- X struct range_st *range;
- X struct int_st *interval;
- X int func;
- X struct parm_st *parm_list;
- X struct trow_st *const_table;
- X} tnode_st;
- X
- Xtypedef struct attr_st {
- X double value;
- X int node_type;
- X struct attr_st *left , *right;
- X char *ident;
- X struct parm_st *parm_list;
- X} attr_st;
- X
- Xtypedef struct expr_list_st {
- X struct attr_st *expr;
- X struct expr_list_st *next;
- X} expr_list_st;
- X
- Xtypedef struct range_st {
- X double min , max;
- X} range_st;
- X
- Xtypedef struct int_st {
- X#define ISIZE 0
- X#define INUMINT 1
- X int int_type;
- X double value;
- X} int_st;
- X
- Xtypedef struct graph_st {
- X int line_type; /* NO,DOTTED,SOLID,LONGDASHED,SHORTDASHED,DOTDASHED */
- X int point_type; /* A mask MSK_TRIANGLE etc */
- X#define MSK_CIRCLE 0x01
- X#define MSK_TRIANGLE 0x02
- X#define MSK_SQUARE 0x04
- X#define MSK_CROSS 0x08
- X#define MSK_PLUS 0x10
- X int cumulative; /* true/false */
- X char *label;
- X char *legend; /* NULL means dont put in legend */
- X table_st *table;
- X} graph_st;
- X
- Xtypedef struct axis_st {
- X char *format; /* printf format for numbering axis */
- X char *user_format; /* user defined format */
- X char *label;
- X int scale; /* AUTO,NO */
- X int frame; /* FRAME,GRID,OUTLINE,NO */
- X int linear; /* LOG,LINEAR */
- X int auto_tick_size; /* true/false */
- X range_st range;
- X int_st *interval;
- X double tick_size;
- X double power_10;
- X} axis_st;
- X
- Xtypedef struct parm_st {
- X int parm_type;
- X char *ident;
- X tnode_st *tab_expr;
- X attr_st *expr;
- X struct parm_st *next;
- X} parm_st;
- X
- Xtypedef struct tcol_st {
- X struct attr_st *expr;
- X struct tcol_st *next;
- X} tcol_st;
- X
- Xtypedef struct trow_st {
- X struct tcol_st *cols;
- X struct trow_st *next;
- X} trow_st;
- X
- SHAR_EOF
- if test 2321 -ne "`wc -c < 'graph.h'`"
- then
- echo shar: error transmitting "'graph.h'" '(should have been 2321 characters)'
- fi
- fi
- if test -f 'yacc.y'
- then
- echo shar: will not over-write existing file "'yacc.y'"
- else
- echo extracting "'yacc.y'"
- sed 's/^X//' >yacc.y <<'SHAR_EOF'
- X/*
- X * Copyright (C) 1986 Alan Kent
- X *
- X * Permission is granted to freely distribute part or
- X * all of this code as long as it is not for profit
- X * and this message is retained in the code.
- X *
- X * No resposibility is taken for any damage or incorect
- X * results this program generates.
- X *
- X */
- X
- X
- X/* Declaration section */
- X
- X%{
- X
- X#include <stdio.h>
- X#include <math.h>
- X#include "graph.h"
- X
- X#define LARGE_INT 16000
- X
- Xextern char *new ();
- Xextern double floor ();
- Xextern table_st *read_table ();
- Xextern table_st *load_table ();
- Xextern attr_st *attr_node ();
- Xextern double eval ();
- Xextern table_st *eval_tab ();
- Xextern tnode_st *tab_node ();
- Xextern parm_st *parm_node ();
- Xextern char *ctime ();
- X
- Xextern int gargc;
- Xextern char **gargv;
- Xextern axis_st xaxis;
- Xextern axis_st yaxis;
- Xextern graph_st graph[];
- Xextern int num_graphs;
- Xextern char *graph_label;
- Xextern int horiz_legend;
- Xextern int vert_legend;
- X
- X
- Xstatic axis_st *paxis;
- X
- X
- X%}
- X
- X%union {
- X attr_st *attr_expr;
- X table_st *table;
- X tnode_st *tnode;
- X double number;
- X char *string;
- X expr_list_st *expr_list;
- X range_st *range;
- X int_st *interval;
- X int integer;
- X parm_st *parm;
- X tcol_st *tcol;
- X trow_st *trow;
- X}
- X
- X%left JOIN SORT GROUP CUMULATE
- X%left BY
- X%left APPEND
- X%left ADJACENT
- X%left '[' WHERE
- X%left <string> STRING IDENT TAB_IDENT VAR_IDENT FTAB_IDENT FVAR_IDENT
- X%left <number> NUMBER
- X
- X%type <string> string_expr string_sub_expr
- X%type <trow> table_line_list
- X%type <tcol> table_line
- X%type <number> constant
- X%type <attr_expr> expr or_op and_op rel_op add_op mul_op primary attr
- X%type <expr_list> expr_list
- X%type <range> range
- X%type <interval> interval
- X%type <string> group_function
- X%type <tnode> table
- X%type <parm> dec_parm_list dec_parm call_parm_list call_parm
- X
- X%start program
- X
- X%token READ SHELL PRINT TABLE XAXIS YAXIS PLOT GRAPH VALUE INCLUDE
- X%token APPEND SORT JOIN GROUP BY WHERE INTO INTERVAL SIZE FROM TO WITH
- X%token PERFORMING ADJACENT DATE PARAMETER SAVE LOAD AS
- X%token LBRACKET RBRACKET LPAREN RPAREN
- X%token EQ NE GE GT LE LT PLUS MINUS DIVIDE MULTIPLY AND OR NOT NEG
- X%token IDENT TAB_IDENT VAR_IDENT STRING ATTR NUMBER FTAB_IDENT FVAR_IDENT
- X%token TICK LABEL FORMAT AUTO NO SCALE FRAME GRID OUTLINE AXIS
- X%token LOGRITHMIC LINEAR DOTTED SOLID LONGDASHED SHORTDASHED DOTDASHED LINE
- X%token QUEST COLON MODULUS TAB_CONST PROJECT CUMULATE GENERATE
- X%token TRIANGLE CIRCLE SQUARE CROSS POINTS POWER
- X%token PUT LEGEND AT TOP MIDDLE BOTTOM LEFT CENTER RIGHT
- X%token STR VAL PARMS ASSUME
- X
- X
- X
- X%%
- X
- X/* Rules section */
- X
- X
- Xprogram: statement_list
- X {
- X if ( num_graphs > 0 ) {
- X dump_graphs ();
- X reset_graphs ();
- X }
- X }
- X ;
- X
- Xstatement_list:
- X | statement statement_list
- X ;
- X
- X
- Xstatement: ';'
- X | IDENT EQ table
- X { tab_declare ( $1 , eval_tab ( $3 ) ); }
- X | TAB_IDENT EQ table
- X { tab_declare ( $1 , eval_tab ( $3 ) ); }
- X | IDENT EQ expr
- X { var_declare ( $1 , eval ( NULL , 0 , $3 ) ); }
- X | VAR_IDENT EQ expr
- X { var_declare ( $1 , eval ( NULL , 0 , $3 ) ); }
- X | IDENT '(' dec_parm_list ')' EQ expr
- X { fun_declare ( $1 , $3 , $6 , NULL ); }
- X | IDENT '(' dec_parm_list ')' EQ table
- X { fun_declare ( $1 , $3 , NULL , $6 ); }
- X | INCLUDE string_expr
- X { include ( $2 ); release ( $2 ); }
- X | SHELL string_expr
- X { system ( $2 ); /* use >file */ release ( $2 ); }
- X | SAVE table AS string_expr
- X { save_table ( $4 , eval_tab ( $2 ) ); release ( $4 ); }
- X | PRINT GT GT string_expr table
- X { print_table ( eval_tab ( $5 ) , $4 , "a" ); release ( $4 ); }
- X | PRINT GT string_expr table
- X { print_table ( eval_tab ( $4 ) , $3 , "w" ); release ( $3 ); }
- X | PRINT table
- X { print_table ( eval_tab ( $2 ) , NULL , NULL ); }
- X | PRINT GT GT string_expr expr
- X { print_expr ( eval ( NULL , 0 , $5 ) , $4 , "a" ); release ( $4 ); }
- X | PRINT GT string_expr expr
- X { print_expr ( eval ( NULL , 0 , $4 ) , $3 , "w" ); release ( $3 ); }
- X | PRINT expr
- X { print_expr ( eval ( NULL , 0 , $2 ) , NULL , NULL ); }
- X | PRINT GT GT string_expr string_expr
- X { print_string ( $5 , $4 , "a" ); release ( $4 ); release ( $5 ); }
- X | PRINT GT string_expr string_expr
- X { print_string ( $4 , $3 , "w" ); release ( $3 ); release ( $4 ); }
- X | PRINT string_expr
- X { print_string ( $2 , NULL , NULL ); release ( $2 ); }
- X | graph
- X | XAXIS
- X { paxis = &xaxis; }
- X axis
- X | YAXIS
- X { paxis = &yaxis; }
- X axis
- X | PUT LEGEND AT pos_list
- X | PLOT
- X { dump_graphs (); reset_graphs (); }
- X | ASSUME expr string_expr
- X {
- X if ( eval ( NULL , 0 , $2 ) == 0.0 ) {
- X fprintf ( stderr , "%s\n" , $3 );
- X exit ( 1 );
- X }
- X release ( $3 );
- X }
- X ;
- X
- Xpos_list: /* empty */
- X | pos pos_list
- X ;
- X
- Xpos: LEFT
- X { horiz_legend = LEFT; }
- X | CENTER
- X { horiz_legend = CENTER; }
- X | RIGHT
- X { horiz_legend = RIGHT; }
- X | TOP
- X { vert_legend = TOP; }
- X | MIDDLE
- X { vert_legend = MIDDLE; }
- X | BOTTOM
- X { vert_legend = BOTTOM; }
- X ;
- X
- Xtable : READ string_expr
- X {
- X $$ = tab_node ( TAB_CONST );
- X $$->table = read_table ( $2 , -1 , -1 );
- X release ( $2 );
- X }
- X | READ expr BY expr string_expr
- X {
- X $$ = tab_node ( TAB_CONST );
- X $$->table = read_table ( $5 ,
- X (int)eval ( NULL , 0 , $2 ) ,
- X (int)eval ( NULL , 0 , $4 ) );
- X release ( $5 );
- X }
- X | LOAD string_expr
- X {
- X $$ = tab_node ( TAB_CONST );
- X $$->table = load_table ( $2 );
- X release ( $2 );
- X }
- X | '{' table_line_list '}'
- X {
- X $$ = tab_node ( TABLE );
- X $$->const_table = $2;
- X }
- X | GENERATE range interval
- X {
- X $$ = tab_node ( GENERATE );
- X $$->range = $2;
- X $$->interval = $3;
- X }
- X | table APPEND table
- X {
- X $$ = tab_node ( APPEND );
- X $$->left = $1;
- X $$->right = $3;
- X }
- X | table ADJACENT table
- X {
- X $$ = tab_node ( ADJACENT );
- X $$->left = $1;
- X $$->right = $3;
- X }
- X | table '[' expr_list ']'
- X {
- X $$ = tab_node ( PROJECT );
- X $$->left = $1;
- X $$->expr_list = $3;
- X }
- X | table WHERE expr
- X {
- X $$ = tab_node ( WHERE );
- X $$->left = $1;
- X $$->expr = $3;
- X }
- X | SORT table BY attr
- X {
- X $$ = tab_node ( SORT );
- X $$->left = $2;
- X $$->expr = $4;
- X }
- X | JOIN table ',' table BY attr ',' attr
- X {
- X $$ = tab_node ( JOIN );
- X $$->left = $2;
- X $$->right = $4;
- X $$->expr = attr_node ( JOIN , (double)0.0 , $6 , $8 );
- X }
- X | CUMULATE table BY attr
- X {
- X $$ = tab_node ( CUMULATE );
- X $$->left = $2;
- X $$->expr = $4;
- X }
- X | GROUP table range interval PERFORMING group_function
- X {
- X $$ = tab_node ( GROUP );
- X $$->left = $2;
- X $$->range = $3;
- X $$->interval = $4;
- X $$->ident = $6;
- X }
- X | '(' table ')'
- X { $$ = $2; }
- X | IDENT
- X { abort ( "Undefined identifier" ); }
- X | FTAB_IDENT '(' call_parm_list ')'
- X {
- X $$ = tab_node ( FTAB_IDENT );
- X $$->ident = $1;
- X $$->parm_list = $3;
- X }
- X | TAB_IDENT
- X { $$ = tab_node ( TAB_IDENT ); $$->ident = $1; }
- X ;
- X
- Xgroup_function:
- X FVAR_IDENT
- X { $$ = $1; check_group_fun ( $1 ); }
- X ;
- X
- Xtable_line_list:
- X { $$ = NULL; }
- X | '{' table_line '}' table_line_list
- X {
- X $$ = (trow_st *) new ( sizeof ( trow_st ) );
- X $$->cols = $2;
- X $$->next = $4;
- X }
- X ;
- X
- Xtable_line: expr
- X {
- X $$ = (tcol_st *) new ( sizeof ( tcol_st ) );
- X $$->expr = $1;
- X $$->next = NULL;
- X }
- X |
- X expr ',' table_line
- X {
- X $$ = (tcol_st *) new ( sizeof ( tcol_st ) );
- X $$->expr = $1;
- X $$->next = $3;
- X }
- X ;
- X
- Xattr : '$' primary
- X { $$ = $2; }
- X ;
- X
- Xexpr : or_op '?' or_op ':' or_op
- X { $$ = attr_node ( QUEST , (double)0.0 , $1 ,
- X attr_node ( COLON , (double)0.0 , $3 , $5 ) ); }
- X | or_op
- X { $$ = $1; }
- X ;
- X
- Xor_op : and_op '|' or_op
- X { $$ = attr_node ( OR , (double)0.0 , $1 , $3 ); }
- X | and_op
- X { $$ = $1; }
- X ;
- X
- Xand_op : rel_op '&' and_op
- X { $$ = attr_node ( AND , (double)0.0 , $1 , $3 ); }
- X | rel_op
- X { $$ = $1; }
- X ;
- X
- Xrel_op : add_op EQ add_op
- X { $$ = attr_node ( EQ , (double)0.0 , $1 , $3 ); }
- X | add_op NE add_op
- X { $$ = attr_node ( NE , (double)0.0 , $1 , $3 ); }
- X | add_op LE add_op
- X { $$ = attr_node ( LE , (double)0.0 , $1 , $3 ); }
- X | add_op LT add_op
- X { $$ = attr_node ( LT , (double)0.0 , $1 , $3 ); }
- X | add_op GE add_op
- X { $$ = attr_node ( GE , (double)0.0 , $1 , $3 ); }
- X | add_op GT add_op
- X { $$ = attr_node ( GT , (double)0.0 , $1 , $3 ); }
- X | add_op
- X { $$ = $1; }
- X ;
- X
- Xadd_op : mul_op '+' add_op
- X { $$ = attr_node ( PLUS , (double)0.0 , $1 , $3 ); }
- X | mul_op '-' add_op
- X { $$ = attr_node ( MINUS , (double)0.0 , $1 , $3 ); }
- X | mul_op
- X { $$ = $1; }
- X ;
- X
- Xmul_op : primary '/' mul_op
- X { $$ = attr_node ( DIVIDE , (double)0.0 , $1 , $3 ); }
- X | primary '*' mul_op
- X { $$ = attr_node ( MULTIPLY , (double)0.0 , $1 , $3 ); }
- X | primary '%' mul_op
- X { $$ = attr_node ( MODULUS , (double)0.0 , $1 , $3 ); }
- X | primary
- X { $$ = $1; }
- X ;
- X
- Xprimary : '-' primary
- X { $$ = attr_node ( NEG , (double)0.0 , $2 , NULL ); }
- X | '!' primary
- X { $$ = attr_node ( NOT , (double)0.0 , $2 , NULL ); }
- X | '(' expr ')'
- X { $$ = $2; }
- X | attr
- X { $$ = attr_node ( ATTR , (double)0.0 , $1 , NULL ); }
- X | constant
- X { $$ = attr_node ( NUMBER , $1 , NULL , NULL ); }
- X | FVAR_IDENT '(' call_parm_list ')'
- X {
- X $$ = attr_node ( FVAR_IDENT , (double)0.0 , NULL , NULL );
- X $$->ident = $1;
- X $$->parm_list = $3;
- X }
- X | VAR_IDENT
- X {
- X $$ = attr_node ( VAR_IDENT , (double)0.0 , NULL , NULL );
- X $$->ident = $1;
- X }
- X ;
- X
- Xexpr_list:
- X { $$ = NULL; }
- X | expr
- X {
- X $$ = (expr_list_st *) new ( sizeof ( expr_list_st ) );
- X $$->expr = $1;
- X $$->next = NULL;
- X }
- X | expr ',' expr_list
- X {
- X $$ = (expr_list_st *) new ( sizeof ( expr_list_st ) );
- X $$->expr = $1;
- X $$->next = $3;
- X }
- X ;
- X
- Xinterval: WITH expr INTERVAL
- X {
- X $$ = (int_st *) new ( sizeof ( int_st ) );
- X $$->int_type = INUMINT;
- X $$->value = eval ( NULL , 0 , $2 );
- X }
- X | INTERVAL SIZE expr
- X {
- X $$ = (int_st *) new ( sizeof ( int_st ) );
- X $$->int_type = ISIZE;
- X $$->value = eval ( NULL , 0 , $3 );
- X }
- X ;
- X
- Xrange : /* default min to max */
- X { $$ = NULL; }
- X | FROM expr TO expr
- X {
- X $$ = (range_st *) new ( sizeof ( range_st ) );
- X $$->min = eval ( NULL , 0 , $2 );
- X $$->max = eval ( NULL , 0 , $4 );
- X }
- X ;
- X
- Xconstant: NUMBER
- X { $$ = $1; }
- X | PARMS
- X { $$ = gargc - 2; }
- X | VAL '(' string_expr ')'
- X {
- X double num;
- X
- X if ( scan_value ( $3 , &num ) == NULL ) {
- X warn ( "Illegal number in VAL()" );
- X num = 0.0;
- X }
- X release ( $3 );
- X $$ = num;
- X }
- X ;
- X
- Xaxis : axis_option_list
- X ;
- X
- Xaxis_option_list:
- X | axis_option axis_option_list
- X ;
- X
- Xaxis_option:
- X /*
- X | TICK range
- X | AUTO TICK
- X */
- X LABEL string_expr
- X { paxis->label = $2; }
- X | FORMAT string_expr
- X { paxis->user_format = $2; }
- X | AUTO SCALE
- X { paxis->scale = AUTO; }
- X | NO SCALE
- X { paxis->scale = NO; }
- X | TICK SIZE expr POWER expr
- X {
- X paxis->auto_tick_size = 0;
- X paxis->tick_size = eval ( NULL , 0 , $3 );
- X paxis->power_10 = eval ( NULL , 0 , $5 );
- X }
- X | TICK SIZE expr
- X {
- X paxis->auto_tick_size = 0;
- X paxis->tick_size = eval ( NULL , 0 , $3 );
- X paxis->power_10 = 0.0; /* not good */
- X }
- X | FRAME AXIS
- X { paxis->frame = FRAME; }
- X | GRID AXIS
- X { paxis->frame = GRID; }
- X | OUTLINE AXIS
- X { paxis->frame = OUTLINE; }
- X | NO AXIS
- X { paxis->frame = NO; }
- X | LOGRITHMIC
- X { paxis->linear = LOGRITHMIC; }
- X | LINEAR
- X { paxis->linear = LINEAR; }
- X | FROM expr TO expr
- X {
- X paxis->range.min = eval ( NULL , 0 , $2 );
- X paxis->range.max = eval ( NULL , 0 , $4 );
- X }
- X ;
- X
- Xgraph : GRAPH table
- X {
- X if ( num_graphs >= MAX_GRAPHS )
- X abort ( "too many graphs" );
- X graph[ num_graphs ].line_type = SOLID;
- X graph[ num_graphs ].point_type = 0;
- X graph[ num_graphs ].cumulative = 0;
- X graph[ num_graphs ].label = NULL;
- X graph[ num_graphs ].legend = NULL;
- X }
- X graph_option_list
- X {
- X table_st *p;
- X
- X p = eval_tab ( $2 );
- X if ( p == NULL || p->next == NULL )
- X abort ( "GRAPH requires two column tables to plot" );
- X if ( p->size < 1 )
- X warn ( "No data in graph to plot" );
- X else
- X graph[ num_graphs++ ].table = p;
- X }
- X | GRAPH LABEL string_expr
- X {
- X graph_label = $3;
- X }
- X ;
- X
- Xgraph_option_list:
- X | graph_option_list graph_option
- X ;
- X
- Xgraph_option: DOTTED LINE
- X { graph[ num_graphs ].line_type = DOTTED; }
- X | SOLID LINE
- X { graph[ num_graphs ].line_type = SOLID; }
- X | SHORTDASHED LINE
- X { graph[ num_graphs ].line_type = SHORTDASHED; }
- X | LONGDASHED LINE
- X { graph[ num_graphs ].line_type = LONGDASHED; }
- X | DOTDASHED LINE
- X { graph[ num_graphs ].line_type = DOTDASHED; }
- X | NO LINE
- X { graph[ num_graphs ].line_type = NO; }
- X | NO POINTS
- X { graph[ num_graphs ].point_type = 0; }
- X | TRIANGLE POINTS
- X { graph[ num_graphs ].point_type |= MSK_TRIANGLE; }
- X | CIRCLE POINTS
- X { graph[ num_graphs ].point_type |= MSK_CIRCLE; }
- X | SQUARE POINTS
- X { graph[ num_graphs ].point_type |= MSK_SQUARE; }
- X | CROSS POINTS
- X { graph[ num_graphs ].point_type |= MSK_CROSS; }
- X | PLUS POINTS
- X { graph[ num_graphs ].point_type |= MSK_PLUS; }
- X | LABEL string_expr
- X { graph[ num_graphs ].label = $2; }
- X | LEGEND string_expr
- X { graph[ num_graphs ].legend = $2; }
- X ;
- X
- Xdec_parm_list:
- X { $$ = NULL; }
- X |
- X dec_parm
- X { $$ = $1; $$->next = NULL; }
- X | dec_parm ',' dec_parm_list
- X { $$ = $1; $$->next = $3; }
- X ;
- X
- Xdec_parm: VAR_IDENT
- X { $$ = parm_node ( $1 , VALUE ); }
- X | TAB_IDENT
- X { $$ = parm_node ( $1 , TABLE ); }
- X ;
- X
- Xcall_parm_list:
- X { $$ = NULL; }
- X |
- X call_parm
- X { $$ = $1; $$->next = NULL; }
- X | call_parm ',' call_parm_list
- X { $$ = $1; $$->next = $3; }
- X ;
- X
- Xcall_parm: expr
- X { $$ = parm_node ( NULL , VALUE ); $$->expr = $1; }
- X | table
- X { $$ = parm_node ( NULL , TABLE ); $$->tab_expr = $1; }
- X ;
- X
- Xstring_expr: string_sub_expr
- X {
- X $$ = $1;
- X }
- X | string_sub_expr '+' string_expr
- X {
- X char *p;
- X
- X p = new ( strlen ( $1 ) + strlen ( $3 ) + 1 );
- X strcpy ( p , $1 );
- X strcat ( p , $3 );
- X release ( $1 );
- X release ( $3 );
- X $$ = p;
- X }
- X ;
- X
- Xstring_sub_expr: STRING
- X {
- X char *p;
- X
- X p = new ( strlen ( $1 ) + 1 );
- X strcpy ( p , $1 );
- X $$ = p;
- X }
- X | PARAMETER constant
- X {
- X char *p;
- X int i;
- X
- X i = $2;
- X if ( i > gargc - 2 || i < 1 )
- X abort ( "undefined parameter" );
- X p = new ( strlen ( gargv[ i + 1 ] ) + 1 );
- X strcpy ( p , gargv[ i + 1 ] );
- X $$ = p;
- X }
- X | STR '(' string_expr ',' expr ')'
- X {
- X char *p;
- X char buf[ 100 ];
- X
- X sprintf ( buf , $3 , eval ( NULL , 0 , $5 ) );
- X p = new ( strlen ( buf ) + 1 );
- X strcpy ( p , buf );
- X release ( $3 );
- X $$ = p;
- X }
- X | STR '(' expr ')'
- X {
- X char *p;
- X char buf[ 30 ];
- X
- X sprintf ( buf , "%g" , eval ( NULL , 0 , $3 ) );
- X p = new ( strlen ( buf ) + 1 );
- X strcpy ( p , buf );
- X $$ = p;
- X }
- X | DATE
- X {
- X long clock;
- X char *p , *str;
- X int i;
- X
- X p = new ( 32 );
- X time ( &clock );
- X str = ctime ( &clock );
- X for ( i = 0; str[i] != '\n' && str[i] != '\0'; i++ )
- X p[i] = str[i];
- X p[i] = '\0';
- X $$ = p;
- X }
- X ;
- X
- X%%
- X
- X/* Subroutine section */
- X
- SHAR_EOF
- if test 15119 -ne "`wc -c < 'yacc.y'`"
- then
- echo shar: error transmitting "'yacc.y'" '(should have been 15119 characters)'
- fi
- fi
- # end of shell archive
- exit 0
-